package com.dongnao.network.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

/**
 * @author sjy
 * @date 2024年05月09日 18:30
 */
public class SocketChannelServer {

    public static void main(String[] args) throws Exception {
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();//打开一个通道，默认是阻塞的
        serverSocketChannel.configureBlocking(false);//设置为非阻塞模式
        serverSocketChannel.socket().bind(new InetSocketAddress(8080));//绑定端口
        System.out.println("服务端启动");
        while (true) {
            //accept 的语义是非阻塞的尝试接受连接。如果没有连接准备好，该方法会返回 null，并不会等待直到有连接进来。
            //需要通过轮询或者结合选择器（Selector）等机制来实现非阻塞地等待连接。
            //获取新tcp连接通道
            SocketChannel socketChannel = serverSocketChannel.accept();
            //tcp请求 读取/响应
            if (socketChannel != null) {
                System.out.println("收到新连接：" + socketChannel);
                socketChannel.configureBlocking(false);//默认是阻塞的，设置为false为非阻塞
                try {
                    ByteBuffer requestBuffer = ByteBuffer.allocate(1024);
                    //read非阻塞的
                    //read(byteBuffer)将客户端数据读取到byteBuffer中，返回的是读取到的字节数，返回-1表示通道已关闭
                    while (socketChannel.isOpen() && socketChannel.read(requestBuffer) != -1) {
                        //长连接下，需要手动判断数据有没有读取结束(此处做一个简单的判断：超过0字节)
                        if (requestBuffer.position() > 0) break;
                        System.out.println("----空转----");
                    }
                    if (requestBuffer.position() == 0) continue;
                    requestBuffer.flip();//转换为读模式
                    byte[] content = new byte[requestBuffer.limit()];
                    requestBuffer.get(content);
                    System.out.println("收到数据，来自：" + socketChannel.getRemoteAddress());
                    System.out.println(new String(content));

                    //响应结果 200
                    String response = "HTTP/1.1 200 OK\r\n" + "Content-Length: 11\r\n\r\n" + "Hello World";
                    ByteBuffer buffer = ByteBuffer.wrap(response.getBytes());
                    while (buffer.hasRemaining()) {
                        socketChannel.write(buffer);//非阻塞
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                System.out.println("----没有新连接，空转----");
            }
        }
    }
}
